﻿namespace MicroCloud.Message
{
    /// <summary>
    /// 消息模块DTO实体映射类
    /// </summary>
    public class AutoMapperMessageConfiguration : AutoMapperTupleBase
    {
        /// <summary>
        /// 初始化一个消息模块DTO实体映射 <see cref="AutoMapperMessageConfiguration"/> 的新实例
        /// </summary>
        /// <param name="provider">服务提供者</param>
        public AutoMapperMessageConfiguration(IServiceProvider provider)
        {
            ServiceProvider = provider;
        }

        /// <summary>
        /// 获取 服务提供者
        /// </summary>
        protected IServiceProvider ServiceProvider { get; }

        /// <summary>
        /// 创建对象映射
        /// </summary>
        public override void CreateMap()
        {
            CreateMap<MessageInputDto, MessageEntity>().ForMember(entity => entity.Payload, opt => opt.MapFrom(dto => ((object)dto.Payload).ToJsonString(false, false, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" })))
                .ForMember(entity => entity.SendWays, opt => opt.MapFrom(dto => dto.SendWays.ToJsonString(false, false)))
                .ForMember(entity => entity.ToUsers, opt => opt.MapFrom(dto => dto.ToUsers.ExpandAndToString(",")))
                .ForMember(entity => entity.ToOrganizations, opt => opt.MapFrom(dto => dto.ToOrganizations.ExpandAndToString(",")))
                .ForMember(entity => entity.ToRoles, opt => opt.MapFrom(dto => dto.ToRoles.ExpandAndToString(",")));
            CreateMap<MessageEntity, MessageOutputDto>().ForMember(dto => dto.Payload, opt => opt.MapFrom(entity => entity.Payload.ToObject(default)))
                .ForMember(dto => dto.SendWays, opt => opt.MapFrom(entity => entity.SendWays.FromJsonString<MessageSendWay[]>()))
                .ForMember(dto => dto.ToUsers, opt => opt.MapFrom(entity => entity.ToUsers.Split(",", true)))
                .ForMember(dto => dto.ToOrganizations, opt => opt.MapFrom(entity => entity.ToOrganizations.Split(",", true)))
                .ForMember(dto => dto.ToRoles, opt => opt.MapFrom(entity => entity.ToRoles.Split(",", true)))
                .ForMember(dto => dto.SenderName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.SenderId).UserName))
                .ForMember(dto => dto.SenderNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.SenderId).NickName))
                .ForMember(dto => dto.CreatorName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.CreatorId).UserName))
                .ForMember(dto => dto.CreatorNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.CreatorId).NickName))
                .ForMember(dto => dto.UpdaterName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.UpdaterId).UserName))
                .ForMember(dto => dto.UpdaterNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.UpdaterId).NickName));
            CreateMap<MessageEntity, MessageDto>().ForMember(dto => dto.Payload, opt => opt.MapFrom(entity => entity.Payload.ToObject(default)))
                .ForMember(dto => dto.SenderName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.SenderId).UserName))
                .ForMember(dto => dto.SenderNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.SenderId).NickName));
            CreateMap<MessageEntity, MessageDtoSimple>().ForMember(dto => dto.SenderName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.SenderId).UserName))
                .ForMember(dto => dto.SenderNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.SenderId).NickName));

            CreateMap<MessageReceiver, MessageReceiverOutputDto>().ForMember(dto => dto.ReceiverName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.ReceiverId).UserName))
                .ForMember(dto => dto.SendWays, opt => opt.MapFrom(entity => entity.SendWays.FromJsonString<MessageSendWay[]>()))
                .ForMember(dto => dto.ReceiverNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.ReceiverId).NickName));

            CreateMap<TemplateMessageInputDto, TemplateMessage>().ForMember(entity => entity.Payload, opt => opt.MapFrom(dto => ((object)dto.Payload).ToJsonString(false, false, new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" })))
                .ForMember(entity => entity.SendWays, opt => opt.MapFrom(dto => dto.SendWays.ToJsonString(false, false)))
                .ForMember(entity => entity.ToUsers, opt => opt.MapFrom(dto => dto.ToUsers.ExpandAndToString(",")))
                .ForMember(entity => entity.ToOrganizations, opt => opt.MapFrom(dto => dto.ToOrganizations.ExpandAndToString(",")))
                .ForMember(entity => entity.ToRoles, opt => opt.MapFrom(dto => dto.ToRoles.ExpandAndToString(",")));
            CreateMap<TemplateMessage, TemplateMessageOutputDto>().ForMember(dto => dto.Payload, opt => opt.MapFrom(entity => entity.Payload.ToObject(default)))
                .ForMember(dto => dto.SendWays, opt => opt.MapFrom(entity => entity.SendWays.FromJsonString<MessageSendWay[]>()))
                .ForMember(dto => dto.ToUsers, opt => opt.MapFrom(entity => entity.ToUsers.Split(",", true)))
                .ForMember(dto => dto.ToOrganizations, opt => opt.MapFrom(entity => entity.ToOrganizations.Split(",", true)))
                .ForMember(dto => dto.ToRoles, opt => opt.MapFrom(entity => entity.ToRoles.Split(",", true)))
                .ForMember(dto => dto.CreatorName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.CreatorId).UserName))
                .ForMember(dto => dto.CreatorNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.CreatorId).NickName))
                .ForMember(dto => dto.UpdaterName, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.UpdaterId).UserName))
                .ForMember(dto => dto.UpdaterNickname, opt => opt.MapFrom(entity => GetUser(ServiceProvider, entity.UpdaterId).NickName));
        }
       
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="provider">服务提供者</param>
        /// <param name="userId">用户编号</param>
        /// <returns></returns>
        protected static UserSimpleDto GetUser(IServiceProvider provider, long? userId)
        {
            if (userId == null)
            {
                return new UserSimpleDto();
            }
            using IServiceScope scope = provider.CreateScope();
            var userRepository = scope.ServiceProvider.GetService<IRepository<User, long>>();
            var user = userRepository.QueryAsNoTracking().Where(o => o.Id == userId).ToCacheFirst<User, UserSimpleDto>(10, false, nameof(UserSimpleDto));
            return user ?? new UserSimpleDto();
        }

    }
}